package com.jy.rhin.domain.document.filter.impl;

import com.jy.api.misc.MiscAPI;
import com.jy.framework.base.entity.Result;
import com.jy.rhin.domain.document.filter.DocumentFilter;
import com.jy.rhin.domain.document.filter.DocumentFilterDescEnum;
import com.jy.rhin.domain.exception.RhinInfraErrorType;
import com.jy.rhin.domain.registration.entity.CodeEnum;
import com.jy.rhin.infra.exception.RhinInfraException;
import com.jy.rhin.infra.uitl.Asserts;
import com.jy.rhin.sdk.dto.document.DocumentContentDto;
import com.jy.rhin.sdk.dto.document.DocumentSubmissionSetDto;
import com.jy.rhin.sdk.dto.document.RhinCodeableDto;
import com.jy.rhin.sdk.dto.document.RhinCodingDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author WeiQ
 * @date 2022/6/9 10:46
 * @Desc 文档内容验证：content能够base64解码，并计算hash/size与入参中的hash/size进行对比
 */
@Slf4j
@Service
public class DocumentFilter4MiscValid implements DocumentFilter {

    @Resource
    MiscAPI miscApi;

    @Override
    public boolean shouldFilter(DocumentSubmissionSetDto submissionSet, List<DocumentContentDto> contentList) {
        return true;
    }

    /**
     * 文档内容验证
     * 遍历校验所有的文档字段值域
     *
     * @param submissionSet
     * @param contentList
     */
    @Override
    public void doFilter(DocumentSubmissionSetDto submissionSet, List<DocumentContentDto> contentList) {

        // 内容类型代码，用于表示该提交集内所有文档的内容分类，一般与文档的classCode一致。
        isExist(submissionSet.getContentTypeCode());

        /*// 文件夹条目
        submissionSet.getFolders().forEach(folderDto -> {
            // 可用状态，固定值为“New”。
            isExist(folderDto.getStatusCode(), CodeEnum.OBJECT_STATUS.getId());
            // 类别代码列表，放入文件夹中文档条目的类别代码列表， 与DocumentEntry的typeCode相对应。
            isExist(folderDto.getTypeCode());
        });*/

        // 文档条目，如果提交集中包含文档则应填充该元素。
        submissionSet.getEntries().forEach(entryDto -> {
            // 可用状态，固定值为“New”。
            isExist(entryDto.getStatusCode(), CodeEnum.OBJECT_STATUS.getId());
            // 文档的粗粒度分类
            //isExist(entryDto.getClassCode());
            // 访问权限
            isExist(entryDto.getConfidentialityCode().getCodeValue(), CodeEnum.CONFIDENTIALITY_CODE.getId());
            // MIME格式
            isExist(entryDto.getMimeType(), CodeEnum.MIME_TYPE.getId());
            // 语言类型
            isExist(entryDto.getLanguageCode(), CodeEnum.LANGUAGE_CODE.getId());
            // 文件格式
            isExist(entryDto.getFormatCode(), CodeEnum.FORMAT_CODE.getId());
          /*  // 就诊机构类型代码
            isExist(entryDto.getHealthcareFacilityTypeCode());
            // 就诊机构专业分类代码
            isExist(entryDto.getPracticeSettingCode());
            // 就诊活动的细粒度分类
            isExist(entryDto.getTypeCode());*/
        });

       /* // 关联条目
        submissionSet.getAssociations().forEach(documentAssociationDto -> {
            // 可用状态，固定值为“New”。
            isExist(documentAssociationDto.getStatusCode(), CodeEnum.OBJECT_STATUS.getId());
            // 关联源的对象状态，值域见第1部分B.8。
            isExist(documentAssociationDto.getSourceStatus(), CodeEnum.ASSOCIATION_STATUS.getId());
            // 关联目标的对象状态，值域见第1部分B.8。
            isExist(documentAssociationDto.getTargetStatus(), CodeEnum.ASSOCIATION_STATUS.getId());
        });*/

    }

    @Override
    public DocumentFilterDescEnum filterDesc() {
        return DocumentFilterDescEnum.MISC_UNIQUENESS;
    }

    /**
     * 判断该值存在值域中，不存在抛出校验异常
     *
     * @param value
     * @return
     */
    private void isExist(RhinCodeableDto value) throws RhinInfraException {
        if (!ObjectUtils.isEmpty(value)) {
            value.getCoding().forEach(this::isExist);
        }
    }

    private void isExist(List<RhinCodeableDto> list) throws RhinInfraException {
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(this::isExist);
        }
    }

    private void isExist(RhinCodingDto value) throws RhinInfraException {
        if (!ObjectUtils.isEmpty(value)) {
            isExist(value.getCodeValue(), value.getCodeSystem());
        }
    }

    /**
     * 判断该值存在值域中，不存在抛出校验异常
     *
     * @param value
     * @param zhiyuCode
     * @return
     */
    private void isExist(String value, String zhiyuCode) throws RhinInfraException {
        Boolean result = null;
        if (!StringUtils.isEmpty(value)) {
            Result<Boolean> booleanResult = miscApi.zhiYuSFCZ(zhiyuCode, value);
            result = booleanResult.getData();
        }
        // 判断值不存在该值域中，抛出校验异常
        Asserts.isTrue(result, RhinInfraErrorType.VALUE_NOT_EXIST_IN_THE_RANGE, " 值域标识符:" + zhiyuCode + " 值:" + value);
    }

}
